package org.fluidripple.socket.operation;

import io.netty.channel.Channel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.fluidripple.socket.protocol.DeviceSerializableProtocol;
import org.fluidripple.socket.protocol.DeviceStartCollectProtocol;
import org.fluidripple.socket.protocol.DeviceStopCollectProtocol;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * 自动化处理
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AutomationOperation implements InitializingBean {
    private static DeviceStopCollectProtocol stopCollectProtocol;
    private static DeviceSerializableProtocol serializableProtocol;
    private static DeviceStartCollectProtocol startCollectProtocol;
    private static List<Channel> channels = new ArrayList<>();
    //延时队列
    private static DelayQueue<DelayedImpl> delayQueue = new DelayQueue();
    @Autowired
    public void init(DeviceStopCollectProtocol deviceStopCollectProtocol,DeviceSerializableProtocol deviceSerializableProtocol,DeviceStartCollectProtocol deviceStartCollectProtocol){
        serializableProtocol = deviceSerializableProtocol;
        stopCollectProtocol = deviceStopCollectProtocol;
        startCollectProtocol = deviceStartCollectProtocol;
    }

    /**
     * 添加并停止采集
     */
    public static void addChannel(Channel channel){
        if (!channels.contains(channel)){
            channels.add(channel);
            stopCollectProtocol.writer(channel);
        }
    }

    /**
     * 获取设备编号
     */
    public static void getDeviceSerializable(Channel channel){
        if (channels.contains(channel)){
            serializableProtocol.writer(channel);
        }
    }
    /**
     * 添加延迟队列
     */
    public static void addDelayQueue(Channel channel){
        if (channels.contains(channel)){
            boolean match = delayQueue.stream().anyMatch(v -> v.getChannel() == channel);
            if (!match){
                //30秒之后执行延时任务
                delayQueue.add(new DelayedImpl(10000L,channel));
            }
        }
    }



    /**
     * 启动采集
     */
    public static void startCollect(Channel channel){
        if (channels.contains(channel)){
            startCollectProtocol.writer(channel);
        }
    }

    /**
     * 删除channel
     */
    public static void delete(Channel channel){
        if (channels.contains(channel)){
            channels.remove(channel);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Thread thread=new Thread(()->{
            for (;;){
                try {
                    DelayedImpl task = delayQueue.take();
                    Channel channel = task.getChannel();
                    getDeviceSerializable(channel);
                    Thread.sleep(500);
                } catch (Exception e) {
                    log.info("异常",e);
                }
            }
        });
        thread.start();
    }


    @Getter
    @Setter
    private static class DelayedImpl implements Delayed{
        //延迟时间，毫秒
        private long delayTime ;
        private Channel channel;

        public DelayedImpl(long delayTime, Channel channel) {
            this.delayTime = delayTime+System.currentTimeMillis();;
            this.channel = channel;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }

        @Override
        public int compareTo(Delayed o) {
            return Long.compare(delayTime, ((DelayedImpl) o).delayTime);
        }
    }
}
